import { ref, watchEffect, type Ref } from 'vue';
import { Immediate, useRequest } from '../useRequest';
import type { IntegratedTable, RowKey, TableFilterValue, TableMapFilter } from '@ykst/components';
import type {
  ApiFuncData,
  BaseQuery,
  PageData,
  RequestFunction,
  ResponseDataWithPager,
} from '@/apis/types';
import { type ApiResponseSuccess } from 'axios';
import { useAppNotification } from '../feedback/useAppNotification';
import { ApiResponseError } from 'axios';

// 分页参数可选
export type QueryPartialPage<T> = Omit<T, keyof PageData> & Partial<PageData>;

export type useListRequest<T, Q> = RequestFunction<T[] | ResponseDataWithPager<T>, any, Q>;

export type useListQuery<Q> = QueryPartialPage<Q> | Ref<QueryPartialPage<Q> | undefined>;

export type useListRequestData = {
  query: BaseQuery & Record<any, any>;
};

export interface useListEmits<T> {
  (e: 'edit', record: T): void;
}

interface useListReturnType<T> {
  /** 请求错误response */
  errRes: Ref<ApiResponseError | null>;
  /** 请求成功response */
  res: Ref<ApiResponseSuccess<T[] | ResponseDataWithPager<T>> | null>;
  /** 数据列表 */
  list: Ref<T[]>;
  /** 数据总数 */
  total: Ref<number>;
  /** 加载状态 */
  loading: Ref<boolean>;
  /** 表格筛选条件，通过 onFilterChange 和 setMapFilter 修改*/
  filterValue: Ref<TableFilterValue | undefined>;
  /** 分页 */
  pagination: Ref<{
    current: number;
    pageSize: number;
  }>;
  /** 选中的行id */
  selectionId: Ref<(string | number)[]>;
  /** 表格第一次请求完成 */
  init: Ref<boolean>;
  /** 组件Ref */
  tableRef: Ref<InstanceType<typeof IntegratedTable> | undefined>;
  /** 刷新表格当前页面 */
  refresh: () => Promise<ApiResponseSuccess<ResponseDataWithPager<T> | T[]> | null | undefined>;
  /** 表格筛选事件 */
  onFilterChange: (value: TableFilterValue) => void;
  /** 重置分页，清空选中，并且刷新请求 */
  resetPageAndRefresh: () => void;
  /**
   * 行选中
   */
  onSelection: (value: (string | number)[]) => void;
  /**
   * 分发编辑事件
   */
  onEdit: (record: T) => void;
  /**
   * @description 校验选中行
   * @param { RowKey[] } [selectedIds] 选中的id ，不传的话使用selectionId.value
   */
  checkSelectedRows: (id?: RowKey[]) => Promise<void>;
  /**
   * 修改filterValue,有些接口的筛选参数写在map里，需要手动修改map值
   * @param mapFilter mapFilter参数
   *
   * @example
   * // 直接使用
   * setMapFilter({eq:{dep_id:props.depId}})
   * // 在watch中使用，建议使用watch，而不是watchEffect 因为表格中的筛选值变化会重复运行watchEffect里的代码
   * watch(() => props.id ,() => { setMapFilter({eq: { dep_id: props.depId }}) })
   */
  setMapFilter: (mapFilter: Partial<TableMapFilter>) => void;
}
/**
 * 请求列表数据
 * @param requestFunc 列表请求函数
 * @param {useListEmits<T>} [emits] 表格的defineEmits定义的事件
 * @param {useListQuery<Q>}  [query] 列表请求函数使用的 query参数 如果是响应式对象，query.value变为undefined时不发送请求
 * @param config 是否有分页或者是否立即请求，immediate同useRequest中的immediate参数
 * @returns
 */

export function useList<T = any, Q = any>(
  requestFunc: useListRequest<T, Q>,
  emits?: useListEmits<T>,
  query?: useListQuery<Q>,
  config?: Immediate | { hasPage?: boolean; immediate?: Immediate },
): useListReturnType<T> {
  const tableRef = ref<InstanceType<typeof IntegratedTable>>();
  const { notification } = useAppNotification();

  /**
   * 表格筛选
   */
  const filterValue = ref<TableFilterValue>();
  function onFilterChange(value: TableFilterValue) {
    // 清空选中
    tableRef.value?.clearSelected();
    filterValue.value = value;
  }
  // 修改filterValue,有些接口的筛选参数写在map里，需要手动修改map值
  function setMapFilter(mapFilter: Partial<TableMapFilter>) {
    const {
      like: _like,
      eq: _eq,
      between: _between,
    }: TableMapFilter = JSON.parse(
      filterValue.value?.mapFilter || '{"like":{},"eq":{},"between":{}}',
    );
    const { like = {}, eq = {}, between = {} } = mapFilter;

    const map = {
      like: {
        ..._like,
        ...like,
      },
      eq: {
        ..._eq,
        ...eq,
      },
      between: {
        ..._between,
        ...between,
      },
    };
    const value: TableFilterValue = filterValue.value ?? { mapFilter: '', paramsFilter: {} };
    value.mapFilter = JSON.stringify(map);
    onFilterChange(value);
  }
  /**
   * 分页
   */
  const pagination = ref({
    current: 1,
    pageSize: 10,
  });
  /** 重置分页并且刷新请求 */
  function resetPageAndRefresh() {
    tableRef.value?.clearSelected();
    if (pagination.value.current === 1) {
      request();
    } else {
      // 修改会自动触发请求
      pagination.value.current = 1;
    }
  }
  /**
   * 请求
   */
  const reqQuery = computed<useListRequestData | undefined>(() => {
    const _query = unref(query);
    const hasPage = typeof config === 'object' ? config?.hasPage : config;
    if (isRef(query) && _query === undefined) {
      return undefined;
    }
    return {
      query: {
        page: hasPage !== false ? pagination.value.current : undefined,
        page_size: hasPage !== false ? pagination.value.pageSize : undefined,
        map: filterValue.value?.mapFilter,
        ...filterValue.value?.paramsFilter,
        ...(_query || {}),
      },
    };
  });

  const list: Ref<T[]> = ref([]),
    total = ref(0);
  const { loading, res, init, errRes, request } = useRequest(
    requestFunc,
    reqQuery as ApiFuncData<any, Q>,
    typeof config === 'object' ? config?.immediate : config,
  );

  watchEffect(() => {
    if (res.value) {
      if (Array.isArray(res.value.data)) {
        list.value = res.value.data;
        total.value = list.value.length;
        return;
      } else if (Array.isArray(res.value.data?.data)) {
        list.value = res.value.data.data;
        total.value = res.value.data.pager.TotalCount;
        return;
      }
    }

    list.value = [];
    total.value = 0;
  });

  /**
   * 行选中
   */
  const selectionId = ref<RowKey[]>([]);
  function onSelection(value: RowKey[]) {
    selectionId.value = value;
  }

  /**
   * @description 校验选中行
   * @param { RowKey[] } [selectedIds] 选中的id ，不传的话使用selectionId.value
   */
  function checkSelectedRows(selectedIds?: RowKey[]) {
    const ids = selectedIds ?? selectionId.value;
    if (ids.length > 0) {
      return Promise.resolve();
    } else {
      notification.fastWarning({ description: '未选择任何数据' });
      return Promise.reject(new Error('没有选中行'));
    }
  }
  /**
   * 编辑
   */

  function onEdit(record: T) {
    emits && emits('edit', record);
  }

  return {
    errRes,
    res,
    list,
    total,
    loading,
    filterValue,
    pagination,
    selectionId,
    init, // 初始化：是否完成第一次请求
    tableRef,
    refresh: request,
    onFilterChange,
    resetPageAndRefresh,
    onSelection,
    onEdit,
    checkSelectedRows,
    setMapFilter,
  };
}
